package com.qiwenshare.stock.indicator.product;

import com.qiwenshare.stock.domain.StockDayInfo;
import com.qiwenshare.stock.domain.StockMonthInfo;
import com.qiwenshare.stock.domain.StockWeekInfo;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import lombok.extern.slf4j.Slf4j;
import org.jfree.data.time.TimeSeries;
import org.ta4j.core.Bar;
import org.ta4j.core.BarSeries;
import org.ta4j.core.BaseBarSeriesBuilder;
import org.ta4j.core.indicators.CCIIndicator;

/**
 * # 8), CCI指标
 *     # http://wiki.mbalib.com/wiki/%E9%A1%BA%E5%8A%BF%E6%8C%87%E6%A0%87
 *     # 顺势指标又叫CCI指标，其英文全称为“Commodity Channel Index”，
 *     # 是由美国股市分析家唐纳德·蓝伯特（Donald Lambert）所创造的，是一种重点研判股价偏离度的股市分析工具。
 *     # 1、当CCI指标从下向上突破﹢100线而进入非常态区间时，表明股价脱离常态而进入异常波动阶段，
 *     # 中短线应及时买入，如果有比较大的成交量配合，买入信号则更为可靠。
 *     # 　　2、当CCI指标从上向下突破﹣100线而进入另一个非常态区间时，表明股价的盘整阶段已经结束，
 *     # 将进入一个比较长的寻底过程，投资者应以持币观望为主。
 *     # CCI, default to 14 days
 */
@Slf4j
public class CCI implements Indicator {

    //
    public double calculateCCI(double[] prices, int n) {
        double up = 0.0, down = 0.0;
        for (int i = 0; i < n; i++) {
            if (prices[i] > prices[i+1]) {
                up += prices[i];
            } else if (prices[i] < prices[i+1]) {
                down += prices[i];
            }
        }
        up = up / (n-1);
        down = down / (n-1);
        double cci = up - down;
        cci = cci / (Math.sqrt(up * down) * Math.sqrt((250 + cci) * (250 - cci)));
        return cci;
    }

    @Override
    public List<StockDayInfo> getDayIndicatorList(List<StockDayInfo> stockdayinfoList) {
        BarSeries series = new BaseBarSeriesBuilder().withName("mySeries").build();
        for(StockDayInfo stockdayinfo : stockdayinfoList) {
//            String dateString = "2022-01-01T00:00:00+00:00";

            DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
            ZonedDateTime zonedDateTime = ZonedDateTime.parse(stockdayinfo.getDate() + "T00:00:00Z", formatter);
            series.addBar(zonedDateTime, stockdayinfo.getOpen(), stockdayinfo.getHigh(), stockdayinfo.getLow(), stockdayinfo.getClose(), stockdayinfo.getVolume());
        }
        CCIIndicator cciIndicator = new CCIIndicator(series, 14);

        List<StockDayInfo> newstockDayinfoList = new ArrayList<StockDayInfo>();
        for (int i = 0; i < stockdayinfoList.size(); i++) {
            StockDayInfo stockdayinfo =  stockdayinfoList.get(i);
            stockdayinfo.setCci(cciIndicator.getValue(i).doubleValue());
            newstockDayinfoList.add(stockdayinfo);
        }
        return newstockDayinfoList;
    }

    @Override
    public List<StockWeekInfo> getWeekIndicatorList(List<StockWeekInfo> stockweekinfoList) {

        return stockweekinfoList;
    }

    @Override
    public List<StockMonthInfo> getMonthIndicatorList(List<StockMonthInfo> stockmonthinfoList) {
        return stockmonthinfoList;
    }

    public static void main(String[] args) {
        CCI cci = new CCI();
        List<StockDayInfo> stockdayinfoList = new ArrayList<>();
        for(int i = 1; i < 30; i++) {
            if( i < 10) {
                stockdayinfoList.add(new StockDayInfo("2021-01-0" + i, i, i + 1, i - 1, 1 + 0.5, i * 100, i*1000));
            } else {
                stockdayinfoList.add(new StockDayInfo("2021-01-" + i, i, i + 1, i - 1, 1 + 0.5, i * 100, i*1000));
            }
        }
        List<StockDayInfo> newStockdayinfoList = cci.getDayIndicatorList(stockdayinfoList);
        for(StockDayInfo stockDayInfo : newStockdayinfoList) {
            log.info("date = {}, cci = {}", stockDayInfo.getDate(), stockDayInfo.getCci());
        }
    }
}
